using System;

namespace TSharp.Core.Util.TypeConvert
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TEnum">The type of the enum.</typeparam>
    public class EnumTypeDetectorImpl<TEnum> : NullableValueTypeDetector<TEnum>
        where TEnum : struct
    {
        private static readonly Type type = typeof(TEnum);

        /// <summary>
        /// Strings the specified s.
        /// </summary>
        /// <param name="s">The s.</param>
        /// <param name="arg">The arg.</param>
        /// <returns></returns>
        public override TEnum? String(string s, TEnum? arg)
        {
            if (System.Enum.IsDefined(type, s))
                return (TEnum)System.Enum.Parse(type, s, false);
            int v;
            if (int.TryParse(s, out v))
            {
                return Int32(v, arg);
            }
            return arg;
        }

        /// <summary>
        /// Enums the specified detector obj.
        /// </summary>
        /// <param name="detectorObj">The detector obj.</param>
        /// <param name="arg">The T arg.</param>
        /// <returns></returns>
        public override TEnum? Enum(Enum detectorObj, TEnum? arg)
        {
            return (TEnum)System.Enum.ToObject(type, detectorObj);
        }

        /// <summary>
        /// Int32s the specified detector obj.
        /// </summary>
        /// <param name="detectorObj">The detector obj.</param>
        /// <param name="arg">The arg.</param>
        /// <returns></returns>
        public override TEnum? Int32(int detectorObj, TEnum? arg)
        {
            return (TEnum)System.Enum.ToObject(type, detectorObj);
        }

        /// <summary>
        /// Int16s the specified detector obj.
        /// </summary>
        /// <param name="detectorObj">The detector obj.</param>
        /// <param name="arg">The arg.</param>
        /// <returns></returns>
        public override TEnum? Int16(short detectorObj, TEnum? arg)
        {
            return (TEnum)System.Enum.ToObject(type, detectorObj);
        }

        /// <summary>
        /// Int64s the specified detector obj.
        /// </summary>
        /// <param name="detectorObj">The detector obj.</param>
        /// <param name="arg">The arg.</param>
        /// <returns></returns>
        public override TEnum? Int64(long detectorObj, TEnum? arg)
        {
            return (TEnum)System.Enum.ToObject(type, detectorObj);
        }

        /// <summary>
        /// Decimals the specified detector obj.
        /// </summary>
        /// <param name="detectorObj">The detector obj.</param>
        /// <param name="arg">The arg.</param>
        /// <returns></returns>
        public override TEnum? Decimal(decimal detectorObj, TEnum? arg)
        {
            return (TEnum)System.Enum.ToObject(type, Convert.ToInt64(detectorObj));
        }

        /// <summary>
        /// DBs the null.
        /// </summary>
        /// <param name="detectorObj">The detector obj.</param>
        /// <param name="arg">The arg.</param>
        /// <returns></returns>
        public override TEnum? DBNull(DBNull detectorObj, TEnum? arg)
        {
            return base.DBNull(detectorObj, arg);
        }

        /// <summary>
        /// Bytes the specified detector obj.
        /// </summary>
        /// <param name="detectorObj">The detector obj.</param>
        /// <param name="arg">The arg.</param>
        /// <returns></returns>
        public override TEnum? Byte(byte detectorObj, TEnum? arg)
        {
            return (TEnum)System.Enum.ToObject(type, detectorObj);
        }
    }
}